//
//  AVIOContext.hpp
//  VideoParse
//
//  Created by xiaerfei on 2020/2/14.
//  Copyright © 2020 erfeixia. All rights reserved.
//

#ifndef AVIOContext_hpp
#define AVIOContext_hpp

#include <stdio.h>
#include "FFURL.hpp"

/**
 * ORing this as the "whence" parameter to a seek function causes it to
 * return the filesize without seeking anywhere. Supporting this is optional.
 * If it is not supported then the seek function will return <0.
 */
#define AVSEEK_SIZE 0x10000

/**
 * Passing this flag as the "whence" parameter to a seek function causes it to
 * seek by any means (like reopening and linear reading) or other normally unreasonable
 * means that can be extremely slow.
 * This may be ignored by the seek code.
 */
#define AVSEEK_FORCE 0x20000


#ifndef SEEK_SET
#define    SEEK_SET    0    /* set file offset to offset */
#endif
#ifndef SEEK_CUR
#define    SEEK_CUR    1    /* set file offset to current plus offset */
#endif
#ifndef SEEK_END
#define    SEEK_END    2    /* set file offset to EOF plus offset */
#endif

/*
*********************************************************************************
*
*                            |              buffer_size              |
*                            |---------------------------------------|
*                            |                                       |
*
*                         buffer          buf_ptr       buf_end
*                            +---------------+-----------------------+
*                            |/ / / / / / / /|/ / / / / / /|         |
*  read buffer:              |/ / consumed / | to be read /|         |
*                            |/ / / / / / / /|/ / / / / / /|         |
*                            +---------------+-----------------------+
*
*                                                         pos
*              +-------------------------------------------+-----------------+
*  input file: |                                           |                 |
*              +-------------------------------------------+-----------------+
*
*
*********************************************************************************
*/
class AVIOContext {
private:
    long fill_buffer();
    long fill_buffer(long offset);
    long fill_buffer_back();
    
public:
    
    AVIOContext();
    ~AVIOContext();
    
    FFURL *ffRRL;
    
    unsigned char *buffer;  /**< Start of the buffer. */
    int buffer_size;        /**< Maximum buffer size */
    unsigned char *buf_ptr; /**< Current position in the buffer */
    unsigned char *buf_end; /**< End of the data, may be less than buffer+buffer_size if the read function returned less data than requested, e.g. for streams where no more data has been received yet. */
    int64_t pos;            /**< position in the file of the current buffer */
    
    bool eof_reached;
    
    int read_packet (u_int8_t *buf, int buf_size);
    int write_packet (u_int8_t *buf, int buf_size);
    /*
        offset: 要 seek 到的位置,可以是相对原始视频的起始位置,可以是相对 io 上下文小 buffer 的起始位置,取决于 whence
        whence: seek 的类型,取值为 AVSEEK_SIZE 、SEEK_CUR 、SEEK_SET、SEEK_END
            AVSEEK_SIZE: 不进行 seek 操作,而是要求返回 视频 buffer 的长度大小

            SEEK_CUR: 表示 offset 是相对 io 上下文小 buffer 开始位置的

            SEEK_SET: 表示 offset 是相对 原始 buffer 开始位置的

            SEEK_END: 表示 offset 是相对 原始 buffer 结束位置的
     */
    int64_t avio_seek (int64_t offset, int whence);
    
    int avio_r8();
    
    unsigned int avio_rl16();
    unsigned int avio_rl24();
    unsigned int avio_rl32();
    unsigned long long avio_rl64();
    
    unsigned int avio_rb16();
    unsigned int avio_rb24();
    unsigned int avio_rb32();
    unsigned long long avio_rb64();
    
    int64_t avio_skip(int64_t offset);
    int64_t avio_tell();
    
};

#endif /* AVIOContext_hpp */
